/******************************************************************************
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * libkperf licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 * Author:
 * Create: 2025-01-13
 * Description: Utility functions for thread binding system
 ******************************************************************************/
#ifndef UTILS_H
#define UTILS_H

#include <vector>
#include <string>
#include <unordered_map>
#include <sched.h>
#include <sys/types.h>
#include <dirent.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <chrono>

namespace ThreadBinding {
namespace Utils {

/**
 * @brief System information structure
 */
struct SystemInfo {
    int total_cpus;
    int numa_nodes;
    std::vector<int> cpu_to_numa_map;
    std::unordered_map<int, std::vector<int>> numa_to_cpus_map;
    
    SystemInfo() : total_cpus(0), numa_nodes(0) {}
};

/**
 * @brief CPU affinity information
 */
struct CpuAffinityInfo {
    std::vector<int> allowed_cpus;
    int numa_id;
    bool is_valid;
    
    CpuAffinityInfo() : numa_id(-1), is_valid(false) {}
};

/**
 * @brief Get system CPU and NUMA information
 * @return SystemInfo structure containing topology information
 */
SystemInfo get_system_info();

/**
 * @brief Get CPU affinity for a specific thread
 * @param tid Thread ID
 * @return CpuAffinityInfo structure
 */
CpuAffinityInfo get_thread_cpu_affinity(int tid);

/**
 * @brief Get CPU affinity for a specific process
 * @param pid Process ID
 * @return CpuAffinityInfo structure
 */
CpuAffinityInfo get_process_cpu_affinity(int pid);

/**
 * @brief Bind thread to specific CPU core
 * @param tid Thread ID
 * @param core_id CPU core ID
 * @return true if successful, false otherwise
 */
bool bind_thread_to_core(int tid, int core_id);

/**
 * @brief Parse CPU range string (e.g., "0-3,5,7-9")
 * @param range_str CPU range string
 * @return Vector of CPU IDs
 */
std::vector<int> parse_cpu_range(const std::string& range_str);

/**
 * @brief Get NUMA ID for a specific CPU core
 * @param core_id CPU core ID
 * @return NUMA node ID, -1 if not found
 */
int get_numa_id_for_core(int core_id);

/**
 * @brief Find processes by keyword in command line
 * @param keyword Keyword to search for
 * @return Vector of process IDs
 */
std::vector<int> find_processes_by_keyword(const std::string& keyword);

/**
 * @brief Get all threads of a process
 * @param pid Process ID
 * @return Vector of thread IDs
 */
std::vector<int> get_process_threads(int pid);

/**
 * @brief Get process name by PID
 * @param pid Process ID
 * @return Process name, empty string if not found
 */
std::string get_process_name(int pid);

/**
 * @brief Get thread name by TID
 * @param tid Thread ID
 * @return Thread name, empty string if not found
 */
std::string get_thread_name(int tid);

/**
 * @brief Check if a process exists
 * @param pid Process ID
 * @return true if process exists, false otherwise
 */
bool process_exists(int pid);

/**
 * @brief Check if a thread exists
 * @param tid Thread ID
 * @return true if thread exists, false otherwise
 */
bool thread_exists(int tid);

/**
 * @brief Format time duration for display
 * @param duration Duration in milliseconds
 * @return Formatted string
 */
std::string format_duration(uint64_t duration_ms);

/**
 * @brief Format percentage for display
 * @param value Value to format
 * @param total Total value for percentage calculation
 * @param precision Number of decimal places
 * @return Formatted percentage string
 */
std::string format_percentage(double value, double total, int precision = 2);

/**
 * @brief Get current timestamp in milliseconds
 * @return Current timestamp
 */
uint64_t get_current_timestamp_ms();

/**
 * @brief Sleep for specified milliseconds
 * @param ms Milliseconds to sleep
 */
void sleep_ms(uint64_t ms);

/**
 * @brief Print formatted output with timestamp
 * @param message Message to print
 * @param verbose Whether to print in verbose mode
 */
void log_message(const std::string& message, bool verbose = false);

/**
 * @brief Print error message
 * @param message Error message
 */
void log_error(const std::string& message);

/**
 * @brief Print warning message
 * @param message Warning message
 */
void log_warning(const std::string& message);

/**
 * @brief Print debug message
 * @param message Debug message
 */
void log_debug(const std::string& message);

} // namespace Utils
} // namespace ThreadBinding

#endif // UTILS_H 